﻿using System;
using System.IO;
using System.Net;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections.Generic;

using WoChu.CF.Version;
using WoChu.CF.Version.Model;
using WoChu.RfClient.Common;


namespace WoChu.RfClient.Login
{
    class AutoUpdate
    {
        private static readonly string MAIN_CONTROL_FILE = "WoChu.RfClient.Entry.exe";
        private static readonly string LOGIN_CONTROL_FILE  = "WoChu.RfClient.Login.dll";
        private static readonly string COMMON_CONTROL_FILE = "WoChu.RfClient.Common.dll";
        private static readonly string ENTITY_CONTROL_FILE = "WoChu.RfClient.Entity.dll";
        //private static readonly string DUTY_CONTROL_FILE = "WoChu.RfClient.Duty.dll";

        private static readonly string APP_PATH = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
        private static readonly string APP_ROOT = System.IO.Path.GetDirectoryName(APP_PATH);
        private static readonly string DEST_PATH = APP_ROOT + "\\DownFile";

        //struct FtpInfo
        //{
        //    public string ip;
        //    public string port;
        //    public string user;
        //    public string pwd;
        //}

        public static void UpdateNewVersion(VersionInfo downloadversion)
        {
            DownLoadObject doownObj = new DownLoadObject(downloadversion);
            doownObj.ProcessingDownload += new DownloadObjectEventDelegate(dl_ProcessingDownload);
            doownObj.DoDownloadByHttp();
            //doownObj.DoDownloadByFtp();
            int _processID = System.Diagnostics.Process.GetCurrentProcess().Id;
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(APP_ROOT + @"\Upgrade.exe", _processID.ToString());
            
            if (startInfo != null && System.IO.File.Exists(startInfo.FileName))
            { 
                System.Diagnostics.Process.Start(startInfo);
            }

            // 更新非主控文件
            //bool needUpdateControlFile = false;
            //updateOtherFile(downloadversion.DownFiles, ref needUpdateControlFile);

            // 更新主控文件
            //if (needUpdateControlFile)
            //{
            //   System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(APP_ROOT + @"\Upgrade.exe", System.Diagnostics.Process.GetCurrentProcess().Id.ToString());
            //    System.Diagnostics.Process.Start(startInfo);
            //}
        }

        //更新非主控程序。
        private static bool updateOtherFile(List<DownloadFileInfo> files, ref bool needUpdateControlFile)
        {
            foreach (DownloadFileInfo file in files)
            {
                string locFileName = file.FILENAME;
                if (string.Compare(locFileName, MAIN_CONTROL_FILE, true) == 0    
                    || string.Compare(locFileName, LOGIN_CONTROL_FILE, true) == 0
                    || string.Compare(locFileName, COMMON_CONTROL_FILE, true) == 0
                    || string.Compare(locFileName, ENTITY_CONTROL_FILE, true) == 0)
                {
                    needUpdateControlFile = true;
                    continue;
                }

                string fileFullPath = DEST_PATH + @"\" + locFileName;
                if (!System.IO.File.Exists(fileFullPath)) continue;
                try
                {
                    string oldFile = APP_ROOT + @"\" + locFileName;
                    System.IO.File.Copy(fileFullPath, oldFile, true);
                    //if (System.IO.File.Exists(oldFile))
                    //{
                    //    System.IO.File.Delete(oldFile);
                    //}
                    //System.IO.File.Move(fileFullPath, oldFile);
                    

                }
                catch 
                {
                    return false;
                }
            }
            return true;
        }

        // 控制进度条
        static void dl_ProcessingDownload(object sender, DownloadObjectEventArgs arg)
        {
            switch (arg.ProcessState)
            {
                case ProcessState.Begin:
                    MyProgressClass.MyProgress.Ticks = arg.FileCount * 5 + 3;
                    MyProgressClass.MyProgress.NextPosition("开始下载...");
                    break;
                case ProcessState.Doing:
                    string msg = arg.CurrentUrlFileName;
                    int po = arg.FileCount;
                    po = MyProgressClass.MyProgress.Position + po;
                    MyProgressClass.MyProgress.Position = po;
                    MyProgressClass.MyProgress.NextPosition(msg);
                    break;
                case ProcessState.End:
                    MyProgressClass.MyProgress.NextPosition("下载完成");
                    MyProgressClass.MyProgress.Position = MyProgressClass.MyProgress.Ticks;
                    break;
                default:
                    break;
            }
        }

        public delegate void DownloadObjectEventDelegate(object sender, DownloadObjectEventArgs arg);

        public class DownloadObjectEventArgs
        {
            private int _FileCount;
            private ProcessState _ProcessState;
            private string _CurrentUrlFileName;

            public DownloadObjectEventArgs(int fileCount, ProcessState processState, string currentUrlFileName)
            {
                _FileCount = fileCount;
                _ProcessState = processState;
                _CurrentUrlFileName = currentUrlFileName;
            }

            public int FileCount
            {
                get
                {
                    return _FileCount;
                }
            }

            public ProcessState ProcessState
            {
                get
                {
                    return _ProcessState;
                }
            }

            public string CurrentUrlFileName
            {
                get
                {
                    return _CurrentUrlFileName;
                }
            }
        }

        public enum ProcessState
        {
            Begin,
            Doing,
            End
        }

        public class DownLoadObject
        {
            private VersionInfo _downloadVersion;
            private DownloadObjectEventDelegate _ProcessingDownload; //进度事件
            public event DownloadObjectEventDelegate ProcessingDownload
            {
                add
                {
                    _ProcessingDownload += value;
                }
                remove
                {
                    _ProcessingDownload -= value;
                }
            }

            private void OnProcessingDownload(DownloadObjectEventArgs arg)
            {
                if (_ProcessingDownload != null)
                    _ProcessingDownload(this, arg);
            }


            public DownLoadObject(VersionInfo downloadVersion)
            {
                _downloadVersion = downloadVersion;
            }

            public void DoDownloadByFtp()
            {
                /*
                const char SPLIT_FLG = '`';
                List<string> ftpIplist = new List<string>();

                Dictionary<string, List<DownloadFileInfo>> filelist = new Dictionary<string, List<DownloadFileInfo>>();
                
                foreach (DownloadFileInfo file in _downloadVersion.DownFiles)
                {
                    string akey = file.FILENAME;
                    //file.SERVERADDRESS + SPLIT_FLG.ToString() 
                    //           + file.SERVERPORT + SPLIT_FLG.ToString()
                    //           + file.LOGINUSER + SPLIT_FLG.ToString()
                    //           + file.LOGINPWS;
                    if (filelist.ContainsKey(akey))
                    {
                        filelist[akey].Add(file);
                    }
                    else
                    {
                        filelist.Add(akey, new List<DownloadFileInfo> { file });
                    }
                }

                Func<string, FtpInfo> getFtpInfo = (key) =>
                {
                    FtpInfo fi = new FtpInfo();
                    string[] split = key.Split(SPLIT_FLG);
                    fi.ip = split[0];
                    fi.port = split[1];
                    fi.user = split[2];
                    fi.pwd = split[3];
                    return fi;
                };

                Action<string, string, string, List<DownloadFileInfo>> doDownLoad = (ftpipport, ftpuser, ftppwd, downfiles) =>
                {
                    string ftpip = ftpipport.Split(':')[0];
                    string port = ftpipport.Split(':')[1];
                    FTPClient ftpclient = new FTPClient(ftpip, "", ftpuser, ftppwd, int.Parse(port));
                    try
                    {
                        ftpclient.Connect();
                        OnProcessingDownload(new DownloadObjectEventArgs(downfiles.Count, ProcessState.Begin, string.Empty));
                        ftpclient.SetTransferType(FTPClient.TransferType.Binary);
                        string ftpBaseDir = ftpclient.PWD();
                        List<string> fileNames = new List<string>();

                        foreach (DownloadFileInfo file in downfiles)
                        {
                            try
                            {
                                // 从FTP下载文件 
                                string sourcepath = file.DOWNLOADURL.Replace("ftp://" + ftpuser + ":" + ftppwd + "@" + ftpip, "");
                                sourcepath = sourcepath.Substring(0, sourcepath.Length - ("/" + file.EXTENSION).Length) + "/";
                                ftpclient.ChDir(ftpBaseDir + sourcepath);
                                ftpclient.GetFile(file.EXTENSION, DEST_PATH, file.FILENAME);
                                file.DOWNLOADCOMPLETE = true;
                                OnProcessingDownload(new DownloadObjectEventArgs(downfiles.Count, ProcessState.Begin, file.FILENAME));
                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                            finally
                            {
                                Application.DoEvents();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        ftpclient.DisConnect();
                    }
                };

                foreach (string key in filelist.Keys)
                {
                    FtpInfo ftpinfo = getFtpInfo(key);
                    doDownLoad(ftpinfo.ip + ":" + ftpinfo.port, ftpinfo.user, ftpinfo.pwd, _downloadVersion.DownFiles);
                }
                */
                OnProcessingDownload(new DownloadObjectEventArgs(0, ProcessState.End, string.Empty));
            }

            public void DoDownloadByHttp()
            {  
              

                Action<string, List<DownloadFileInfo>> doDownLoad = (releaseNote, downfiles) =>
                { 
                    FileStream fstream = null;
                    WebRequest wRequest = null;

                    try
                    {
                        
                        foreach (DownloadFileInfo file in downfiles)
                        {                            
                            if (!Directory.Exists(DEST_PATH))
                            {
                                DirectoryInfo directoryInfo = new DirectoryInfo(DEST_PATH);
                                directoryInfo.Create();
                            }

                            string DownFile = DEST_PATH + "\\" + file.FILENAME;
                            if (System.IO.File.Exists(DownFile))
                            {
                                System.IO.File.Delete(DownFile);
                            }

                            //string url = file.DOWNLOADURL;
                            file.DOWNLOADURL = "http://" + AppSetting.NewInstance.GetString("Server") + "/DownFile/" + releaseNote + "/" + file.FILENAME;
                            wRequest = WebRequest.Create(file.DOWNLOADURL);
                            WebResponse wResponse = wRequest.GetResponse();
                            
                            fstream = new FileStream(DownFile, FileMode.Create, FileAccess.Write);

                            int contentLength = (int)wResponse.ContentLength;
                            OnProcessingDownload(new DownloadObjectEventArgs(contentLength, ProcessState.Begin, string.Empty));
                            byte[] buffer = new byte[1024];
                            int read_count = 0;
                            int total_read_count = 0;
                            bool complete = false;
                            while (!complete)
                            {
                                read_count = wResponse.GetResponseStream().Read(buffer, 0, buffer.Length);
                                if (read_count <= 0)
                                {
                                    complete = true;
                                    break;
                                }

                                fstream.Write(buffer, 0, read_count);
                                total_read_count += read_count;
                                if (total_read_count <= contentLength)
                                {
                                    OnProcessingDownload(new DownloadObjectEventArgs(total_read_count, ProcessState.Doing, file.FILENAME));
                                }
                            }

                            file.DOWNLOADCOMPLETE = true;
                            wResponse.Close();

                            fstream.Flush();

                        }


                    }
                    catch (Exception ee)
                    {
                        string e = ee.ToString();
                    }
                    finally 
                    {
                        fstream.Close();
                        wRequest = null;
                    }
                
                };

                doDownLoad(_downloadVersion.RELEASENOTE, _downloadVersion.DownFiles);
                
                OnProcessingDownload(new DownloadObjectEventArgs(0, ProcessState.End, string.Empty));
            }        
        }

        
    }
}
